package com.avantis.admin.config;

import com.avantis.admin.config.shiro.JwtFilter;
import com.avantis.admin.config.shiro.YaphetsAuthorizationAttributeSourceAdvisor;
import com.avantis.admin.config.shiro.YaphetsCacheManager;
import com.avantis.admin.config.shiro.YaphetsRealm;
import com.avantis.admin.service.PermissionService;
import com.avantis.common.entity.Permission;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @Auther: tracywang
 * @Date: 2018/11/12
 * @Description:
 */
@Configuration
public class ShiroConfig {

    @Autowired
    private PermissionService permissionService;

    @Bean
    public YaphetsRealm jiaRealm() {
        YaphetsRealm myRealm = new YaphetsRealm();

        //添加缓存
        myRealm.setCachingEnabled(true);
        myRealm.setAuthenticationCachingEnabled(true);
        myRealm.setAuthorizationCachingEnabled(true);

        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        hashedCredentialsMatcher.setStoredCredentialsHexEncoded(false);
        hashedCredentialsMatcher.setHashIterations(2);//散列的次数，相当于 md5(md5(""));
        myRealm.setCredentialsMatcher(hashedCredentialsMatcher);

        return myRealm;
    }

    @Bean
    public DefaultWebSecurityManager securityManager(YaphetsRealm yaphetsRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(yaphetsRealm);
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator sessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        sessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(sessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        //添加缓存
        securityManager.setCacheManager(jiaCacheManager());
        return securityManager;
    }

    @Bean
    public YaphetsCacheManager jiaCacheManager() {
        return new YaphetsCacheManager();
    }

    @Bean
    public FilterRegistrationBean shiroFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new DelegatingFilterProxy("shiroFilter"));
        registration.setEnabled(true);
        registration.addUrlPatterns("/*");
        registration.setDispatcherTypes(DispatcherType.REQUEST);
        registration.addInitParameter("targetFilterLifecycle", "true");
        return registration;
    }

    @Bean
    public JwtFilter createJwtFilter(){
        return new JwtFilter();
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        Map<String, Filter> filterMap = new HashMap<>();
        filterMap.put("jwt", createJwtFilter());
        factoryBean.setFilters(filterMap);
        factoryBean.setSecurityManager(securityManager);

        factoryBean.setUnauthorizedUrl("/401");

        // 如果不设置默认会自动寻找Web工程根目录下的"/login.html"页面
        factoryBean.setLoginUrl("/login");
        // 登录成功后要跳转的链接
        factoryBean.setSuccessUrl("/initPage");

        //拦截器.
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/druid/**", "anon");
        filterChainDefinitionMap.put("/favicon.png","anon");//解决弹出favicon.ico下载
        filterChainDefinitionMap.put("/logout", "logout");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/swagger-ui.html", "anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**", "anon");
        filterChainDefinitionMap.put("/v2/**", "anon");
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/img/**", "anon");
        filterChainDefinitionMap.put("/font-awesome/**", "anon");

        filterChainDefinitionMap.put("/**", "jwt");
        factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return factoryBean;
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public YaphetsAuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager, YaphetsAuthorizationAttributeSourceAdvisor advisor) {
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    @Bean
    public YaphetsAuthorizationAttributeSourceAdvisor jiaAuthorizationAttributeSourceAdvisor() {
        return new YaphetsAuthorizationAttributeSourceAdvisor();
    }


}
